package br.academia.negocio;

import org.hibernate.HibernateException;

import br.academia.arq.dao.CidadeDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Cidade;
import br.academia.util.Validador;

/** 
 * Processador para validação de negócio de operações
 * relacionadas a Cidade
 * 
 * @see Cidade
 */
public class CidadeProcessador extends AbstractProcessador<Cidade>{

	@Override
	public void execute(TipoOperacao operacao, Cidade obj) throws NegocioException{
		try {
			if(operacao.equals(CADASTRAR)){
				validarCadastro(obj);
				cadastrar(obj);
			}else if(operacao.equals(ALTERAR)){
				validarAlteracao(obj);
				alterar(obj);
			}else if(operacao.equals(REMOVER)){
				validarRemocao(obj);
				remover(obj);
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new NegocioException("Não foi possível realizar a operação. Contate a administração do sistema.");
		} catch (DAOException e) {
			throw new NegocioException(e.getMessage());
		}
	}
	
	/**
	 * Método que valida se o nome/estado setado em uma Cidade já tem um correspondente
	 * no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void validarNomeEstado(Cidade obj) throws NegocioException, HibernateException, DAOException{
		CidadeDAO dao = null;
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			Cidade cidade = dao.findCidadeByNomeEstado(obj.getNome(), obj.getEstado());
			
			if(!Validador.isEmpty(cidade) && cidade.getId() != obj.getId()){
				throw new NegocioException("Já existe uma cidade chamada " + obj.getNome() + " no Estado selecionado.");
			}
		}finally{
			if(dao != null){
				dao.close();
			}
		}
		
	}
	
	/**
	 * Método que faz as validações necessárias para o cadastro
	 * de uma Cidade nova no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarCadastro(Cidade obj) throws HibernateException, NegocioException, DAOException{
		validarNomeEstado(obj);
	}
	
	/**
	 * Método que insere uma Cidade no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void cadastrar(Cidade obj) throws NegocioException, HibernateException, DAOException{
		CidadeDAO dao = null;
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			dao.save(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a alteração
	 * de uma Cidade no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarAlteracao(Cidade obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou uma Cidade inválida.");
		}
		
		validarNomeEstado(obj);
	}
	
	/**
	 * Método que atualiza uma Cidade no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void alterar(Cidade obj) throws NegocioException, HibernateException, DAOException{
		CidadeDAO dao = null;
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			dao.update(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a remoção
	 * de uma Cidade no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarRemocao(Cidade obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou uma Cidade inválida.");
		}else{
			CidadeDAO dao = null;
			Cidade Cidade = null;
			
			try {
				dao = getDAO(CidadeDAO.class);
				
				Cidade = dao.findByPrimaryKey(obj.getId(), Cidade.class);
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(Validador.isEmpty(Cidade)){
				throw new NegocioException("Não foi possível encontrar a Cidade selecionada no nosso banco de dados.");
			}
		}
	}
	
	/**
	 * Método que remove uma Cidade do banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void remover(Cidade obj) throws NegocioException, HibernateException, DAOException{
		CidadeDAO dao = null;
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			dao.delete(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
}
